package menu
{
	import com.*;
	import com.Logging.ClientAction;
	import com.Logging.ClientActionType;
	
	import data.*;
	
	import events.GCEvent;
	
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.utils.Dictionary;
	
	import ui.button.GCButton;
	import ui.list.GCItemScrollList;
	import ui.list.ScrollList;
	import ui.popup.GCConfirmationPopup;
	import ui.popup.GCTextPopup;
	import ui.textfield.*;
	
	
	/**
	 * Menu component for creating items from recipes
	 * @author Jason Won
	 */
	public class GCSynthesizeMenu extends Sprite implements GCSuperMenu
	{
		private var _recipeListDisplay:GCItemScrollList;
		
		// This holds all text regarding the description of a recipe.
		private var _descriptionBox:Sprite;		
		private var _buildButton:GCButton;
		private var _exitButton:GCButton;
		private var _descriptionText:GCTextField;
		
		// Labels
		private var _recipesOnShip:GCStylizedText;
		private var _recipesDescription:GCStylizedText;
		
		// Popup
		private var _confirmationPopup:GCConfirmationPopup;
		private var _notificationPopup:GCTextPopup;
		
		// Helper Variables
		private var _recipeIdOnFocus:uint;
		private var _ingredients:Dictionary;
		private var _canBuild:Boolean;
		private var _lineCount:int;
		private var _textHeight:int = 10;
		private const _verticalPadding:int = 10;
		
		// Tutorial
		private var _firstTimeEntered:Boolean;
		
		public function GCSynthesizeMenu() 
		{
			_lineCount = 0;
			
			// Menu Background
			this.graphics.beginFill(GCConstants.COLOR_GOLD);
			this.graphics.drawRect(0, 0, GCMainDisplay.WIDTH, GCMainDisplay.HEIGHT);
			this.graphics.endFill();
			
			// Create the recipes list
			_recipeListDisplay = new GCItemScrollList(300, 400);
			
			// Create the UI elements
			_descriptionBox = new Sprite();
			_buildButton = new GCButton(onBuildClick);			
			_exitButton = new GCButton(onExit);
			
			// Labels
			_recipesOnShip = new GCStylizedText();
			_recipesDescription = new GCStylizedText();
			
			// Popup
			_confirmationPopup = new GCConfirmationPopup(onBuildConfirm);
			_notificationPopup = new GCTextPopup("You do not have enough materials.", onNotificationClose);
			
			// Helper vaiables
			_ingredients = null;
			_recipeIdOnFocus = 0;
			_canBuild = false;

			_firstTimeEntered = true;
			
			init();	
		}
		
		/**
		 * Initialize all the UI components in this menu here.
		 */
		private function init():void
		{
			// Define the list component
			_recipeListDisplay.x = 50;
			_recipeListDisplay.y = 30;
			_recipeListDisplay.addEventListener(GCEvent.LIST_ITEM_SELECTED_EVENT, onItemSelect);			
			
			// Define the UI components
			_descriptionBox.x = 400;
			_descriptionBox.y = 30;
			_descriptionBox.graphics.beginFill(0x222222);
			_descriptionBox.graphics.drawRect(0, 0, 300, 400);
			_descriptionBox.graphics.endFill();
			
			_exitButton.loadGraphic(GCResources.plate, 100, 30);
			_exitButton.loadText("Exit");
			_exitButton.x = 600;
			_exitButton.y = 480;
			
			_buildButton.loadGraphic(GCResources.plate, 100, 30);
			_buildButton.loadText("Build");
			_buildButton.x = _descriptionBox.x + _descriptionBox.width - _buildButton.width;
			_buildButton.y = _descriptionBox.y + _descriptionBox.height - _buildButton.height;
			_buildButton.visible = false;
			
			// Labels
			_recipesOnShip.setBgStyle(GCStylizedText.STYLE_ONE, _recipeListDisplay.width, 30);
			_recipesOnShip.x = _recipeListDisplay.x;
			_recipesOnShip.text = "Recipes on the Ship";
			_recipesDescription.setBgStyle(GCStylizedText.STYLE_ONE, _descriptionBox.width, 30);
			_recipesDescription.x = _descriptionBox.x;
			_recipesDescription.text = "Recipes Description";
			
			// Popup
			_confirmationPopup.addEventListener(GCEvent.CANCEL_EVENT, onBuildCancel);
			
			this.addChild(_recipesOnShip);
			this.addChild(_recipesDescription);
			this.addChild(_recipeListDisplay);
			this.addChild(_descriptionBox);
			this.addChild(_exitButton);
			this.addChild(_buildButton);
		}		
		
		/**
		 * This function is called whenever the user clicks on the recipes button.
		 */
		public function openMenu(shipInventory:GCInventory):void
		{
			_recipeListDisplay.setFilter(GCItemData.ITEM_TYPE_RECIPE);
			_recipeListDisplay.loadInventory(shipInventory);
			
			if (GCPlayState.tutorialSequence.currentTutorialStage == GCTutorial.STAGE_ESTABLISH_NEW_CENTER &&
			_firstTimeEntered)
			{
				var description:String = "From here you can make upgrades from recipes. Gather the required ingredients to build the item. Once a recipe is used it is gone " +
								" and you'll need to find another to build that item again.";
				GCPlayState.disableScreen(new GCTextPopup(description, GCPlayState.enableScreen));
				_firstTimeEntered = false;
			}
		}
		
		/**
		 * This function gets called whenver the menu gets closed. Include logic
		 * to clean up the menu here (i.e. clearing the list and description
		 * areas)
		 */
		public function closeMenu():void
		{
			_recipeListDisplay.removeAll();
			_buildButton.visible = false;
			_lineCount = 0;
			clearDescription();
		}
		
		//----------------------------------------------------------------------
		//	PUBLIC FUNCTIONS
		//----------------------------------------------------------------------
		
		/**
		 * Method to call to refresh any dynamic parts on the menu
		 */
		public function refresh():void
		{
			_recipeListDisplay.redraw();
		}
		
		//----------------------------------------------------------------------
		//	PRIVATE FUNCTIONS
		//----------------------------------------------------------------------		
		
		/**
		 * Forms the ingredient requirement text
		 * 
		 * @param	recipeId
		 */		
		private function getIngredientText(recipeId:uint):String
		{
			_canBuild = true;
			_ingredients = GCItemData.getRecipeIngredientsFromId(recipeId);
			var shipInv:GCInventory = GCPlayState.getPlayerInventory();
			
			var ingredientText:String = "";
			
			for (var obj:Object in _ingredients)
			{
				var ingredientId:uint = obj as uint;
				var itemInShip:GCItem = shipInv.getItemFromId(ingredientId);
				var amountInShip:uint = 0;
				if (itemInShip != null)
				{
					amountInShip = itemInShip.quantity;
				}
								
				ingredientText += GCItemData.getNameFromId(ingredientId) + ": \t" + String(amountInShip);								
				
				var requiredQuantity:int = _ingredients[ingredientId];
				
				ingredientText += "/" + String(requiredQuantity) + "\n";
				_canBuild = _canBuild && (amountInShip >= requiredQuantity);
			}
			return ingredientText;
		}
		
		private function clearDescription():void
		{
			while (_descriptionBox.numChildren > 0)
			{
				_descriptionBox.removeChildAt(0);
			}		
		}
		
		private function addIngredientDescription(recipeId:uint):void
		{
			_canBuild = true;			
			_ingredients = GCItemData.getRecipeIngredientsFromId(recipeId);
			var shipInv:GCInventory = GCPlayState.getPlayerInventory();
			var cityInv:GCInventory = GCPlayState.getCurrentCity().getInventoryFromCity();
			
			for (var obj:Object in _ingredients)
			{
				var ingredientId:uint = obj as uint;
				var itemInShip:GCItem = shipInv.getItemFromId(ingredientId);
				var amountInShip:uint = 0;
				var amountInCity:uint = 0;
				
				var ingredientImage:Bitmap = GCResources.getResource(GCItemData.getNameFromId(ingredientId));
				ingredientImage.x = _verticalPadding;
				ingredientImage.y = _lineCount;
				_lineCount += ingredientImage.height + 20;
				_descriptionBox.addChild(ingredientImage);
				
				if (itemInShip != null)
				{
					amountInShip = itemInShip.quantity;					
				}
				
				if (cityInv != null)
				{
					var itemInCity:GCItem = cityInv.getItemFromId(ingredientId);
					if (itemInCity != null)
					{
						amountInCity = itemInCity.quantity;
					}
				}
				var requiredQuantity:int = _ingredients[ingredientId];
				
				
				// Create the textfields
				var nameText:TextField = new TextField();				
				var ownText:TextField = new TextField();
				var requiredText:TextField = new TextField();
				
				// Fill the textfields with text
				nameText.text = "\t" + GCItemData.getNameFromId(ingredientId) + ": \t\t\t";
				nameText.textColor = GCConstants.COLOR_WHITE;
				ownText.text = String(amountInShip + amountInCity);
				ownText.textColor = (amountInShip + amountInCity < requiredQuantity) ? GCConstants.COLOR_RED : GCConstants.COLOR_WHITE;
				requiredText.text = "  /  " + String(requiredQuantity);
				requiredText.textColor = GCConstants.COLOR_WHITE;
				
				nameText.autoSize = TextFieldAutoSize.RIGHT;
				ownText.autoSize = TextFieldAutoSize.RIGHT;
				requiredText.autoSize = TextFieldAutoSize.LEFT;
				nameText.selectable = false;
				ownText.selectable = false;
				requiredText.selectable = false;
				
				// Align the textfields
				nameText.x = ingredientImage.x + ingredientImage.width;
				nameText.y = ingredientImage.y + ingredientImage.height/3;
				ownText.x = nameText.x + nameText.width;
				ownText.y = nameText.y;
				requiredText.x = ownText.x + ownText.width;
				requiredText.y = ownText.y;
				
				// Add the textfields
				_descriptionBox.addChild(nameText);
				_descriptionBox.addChild(ownText);
				_descriptionBox.addChild(requiredText);
				
				// Check if the user has enough items to build
				_canBuild = _canBuild && (amountInShip + amountInCity >= requiredQuantity);
			}
		}
		
		//----------------------------------------------------------------------
		//	EVENT HANDLERS
		//----------------------------------------------------------------------		
		
		/**
		 * Dispatches an exit event
		 * @param	event
		 */
		private function onExit(event:MouseEvent):void
		{
			dispatchEvent(new GCEvent(GCEvent.EXIT_MENU_EVENT));
		}
		
		/**
		 * Handles the preperation of building items
		 * @param	event
		 */
		private function onBuildClick(event:MouseEvent):void
		{
			// Check whether the user has enough ingredients to build the item
			if (_canBuild)
			{
				var message:String = "Are you sure you want to build the ";
				message += GCItemData.getNameFromId(GCItemData.getSynthesizedItemFromId(_recipeIdOnFocus)) + "\n";
				
				_confirmationPopup.initializePopup(message);
				GCPlayState.disableScreen(_confirmationPopup);
			}
			else
			{
				GCPlayState.disableScreen(_notificationPopup);
			}
		}
		
		/**
		 * Handles the logic of actually building an item
		 * @param	event
		 */
		private function onBuildConfirm(event:MouseEvent):void
		{
			var shipInv:GCInventory = GCPlayState.getPlayerInventory();
			var cityInv:GCInventory = GCPlayState.getCurrentCity().getInventoryFromCity();
			var shipInvItemId:uint = 0;
			var cityInvItemId:uint = 0;
			
			// Remove the ingredients from the inventory
			for (var obj:Object in _ingredients)
			{
				var ingredientId:uint = obj as uint;
				var requiredQuantity:int = _ingredients[ingredientId];
				var quantityToRemoveShip:uint = 0;
				var quantityToRemoveCity:uint = 0;
				
				var ingredientShipObject:GCItem = shipInv.getItemFromId(ingredientId);
				var ingredientCityObject:GCItem;
				if (ingredientShipObject != null)
				{
					shipInvItemId = ingredientShipObject.invItemId;
					
					// Remove some quantity from the ship, could be all or some
					quantityToRemoveShip = (ingredientShipObject.quantity >= requiredQuantity) ?
						requiredQuantity : requiredQuantity - ingredientShipObject.quantity;
				}
				
				// Check if we need and can take ingredients from the ship
				if (cityInv != null && quantityToRemoveShip < requiredQuantity)
				{
					// At this point we know there is enough in the warehouse
					// The quantity to remove from warehouse is whatever is leftover
					ingredientCityObject = cityInv.getItemFromId(ingredientId);
					cityInvItemId = ingredientCityObject.invItemId;
					quantityToRemoveCity = requiredQuantity - quantityToRemoveShip;
				}
				
				onRemoveIngredient(ingredientId, quantityToRemoveShip, shipInvItemId, quantityToRemoveCity, cityInvItemId);
			}
			
			// Remove ingredient from the database
			function onRemoveIngredient(ingredientId:uint, quantityToRemoveShip:uint, shipInvItemId:uint, quantityToRemoveCity:uint, cityInvItemId:uint):void
			{
				// Remove the item from the ship inventory
				if (quantityToRemoveShip > 0)
				{
					shipInv.removeFromInventory(ingredientId, quantityToRemoveShip);
					
					if (!GCConstants.DEBUG_MODE)
					{
						//DATABASE CALL- remove ingredients from player's ship inventory
						GCUtil.updateItemQuantity(shipInvItemId, quantityToRemoveShip, function(code:uint, data:Object):void
						{
							trace("DATABASE-- removed ingredients for recipe");
						});
					}
				}
				
				// Remove item from the city inventory
				if (quantityToRemoveCity > 0)
				{
					cityInv.removeFromInventory(ingredientId, quantityToRemoveCity);
					
					if (!GCConstants.DEBUG_MODE)
					{
						//DATABASE CALL- remove ingredients from player's ship inventory
						GCUtil.updateItemQuantity(cityInvItemId, quantityToRemoveCity, function(code:uint, data:Object):void
						{
							trace("DATABASE-- removed ingredients for recipe");
						});
					}
				}
			}
			
			// Remove the recipe
			var recipeUsedObject:GCItem = shipInv.getItemFromId(_recipeIdOnFocus);
			var numRecipes:uint = recipeUsedObject.quantity;
			
			//DATABASE CALL- remove the recipe that was used
			if (!GCConstants.DEBUG_MODE)
			{
				GCUtil.updateItemQuantity(recipeUsedObject.invItemId, numRecipes - 1, function(code:uint, data:Object):void
				{
				});
			}
			shipInv.removeFromInventory(_recipeIdOnFocus, 1);
			
			/*
			 * Figure out what item should be added to the player's ship inventory, or their ship collection
			 * if they built a new ship.
			 */
			if (GCItemData.getTypeFromId(_recipeIdOnFocus) == GCItemData.ITEM_TYPE_RECIPE)
			{
				var synthesizedItemId:uint = GCItemData.getSynthesizedItemFromId(_recipeIdOnFocus);
				
				if (GCConstants.DEBUG_MODE)
				{
					// Add the newly made item to the inventory
					shipInv.addQuantityToInventory(0, synthesizedItemId, 1);
				}
				else
				{
					//DATABASE CALL- add the new upgrade to the ship inventory
					GCUtil.addToInventory(GCPlayState.getPlayerId(), synthesizedItemId, GCCityData.CITY_SHIP, 1, function(code:uint, data:Object):void
					{
						var newInvItemId:uint = data["id"];
						
						// Add the newly made item to the inventory
						shipInv.addQuantityToInventory(newInvItemId, synthesizedItemId, 1);
					});
				}
			}
			else
			{ // ITEM_TYPE_SHIP_RECIPE
				var newShipType:uint =  GCItemData.getSynthesizedItemFromId(_recipeIdOnFocus)
			
				//DATABASE CALL- create and add a new ship to the player's collection
				if (GCConstants.DEBUG_MODE)
				{
					createNewShip(0);
				}
				else
				{
					GCUtil.addShip(GCPlayState.getPlayerId(), newShipType, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, function(code:uint, data:Object):void
					{
						var newShipId:uint = data["id"];
						createNewShip(newShipId);
					});
				}
				
				function createNewShip(sid:uint):void
				{
					var numSlotsToAdd:uint = GCShipData.getStatsFromId(newShipType)[3];
					var upgrades:Dictionary = new Dictionary();
					for (var i:uint = 0; i < numSlotsToAdd; i++)
					{
						if (!GCConstants.DEBUG_MODE)
						{
							//DATABASE CALL- initialize the upgrade slots of the new ship to contain null items
							GCUtil.equipItemToShip(sid, i, GCItemData.ITEM_NULL, 0, 0, 0, 0, 0, 0, function(code:uint, data:Object):void
							{
							});
						}
						upgrades[i] = GCItemData.ITEM_NULL;
					}
					GCPlayState.addShip(new GCShip(sid, newShipType, upgrades));
				}
			}
			
			// Redraw the description
			_recipeListDisplay.loadInventory(shipInv);
			_descriptionText.text = "";
			_buildButton.visible = false;
			_buildButton.disable();
			
			// Clean up the popup
			_confirmationPopup.clearPopup();
			GCPlayState.enableScreen();
			GCPlayState.addNewnotification("A new item was synthesized!");
			
			/*
			 * Roy-- tutorial 
			 * Checking if they built a recipe required for the tutorial
			 */
			if (GCPlayState.tutorialSequence.currentTutorialStage == GCTutorial.STAGE_ESTABLISH_NEW_CENTER)
			{
				var templateId:uint = GCQuestData.QUEST_TEMPLATE_TUTORIAL_15;
				if (GCPlayState.tutorialSequence.getTutorialQuestFromTemplate(templateId) != null)
				{
					GCPlayState.dispatchTutorialComplete(templateId);
				}
			}
			
			if (GCConstants.LOGGING_DATA)
			{
				var o:Object = new Object();
				o["itemId"] = _recipeIdOnFocus;
				GCPlayState.logger.LogAction(new ClientAction(ClientActionType.USE_RECIPE, o));
			}
		}
		
		/**
		 * Will close and clear the build popup 
		 * @param	event
		 */
		private function onBuildCancel(event:GCEvent):void
		{
			// Clean up the popup
			_confirmationPopup.clearPopup();
			GCPlayState.enableScreen();
		}
		
		/**
		 * Closes and clears the notification popup
		 * @param	event
		 */
		private function onNotificationClose(event:MouseEvent=null):void
		{
			// Clean up the notification popup
			GCPlayState.enableScreen();
		}
		
		
		/**
		 * Fills the description box when an item is clicked
		 * @param	event
		 */
		private function onItemSelect(event:GCEvent = null):void
		{
			// Return if no item is selected
			if (_recipeListDisplay.selected == null)
				return;
				
			clearDescription();
			_lineCount = 0;
			
			_recipeIdOnFocus = _recipeListDisplay.selected.reference.itemId;
			var recipeName:String = GCItemData.getNameFromId(GCItemData.getSynthesizedItemFromId(_recipeIdOnFocus));
			var description:String = GCItemData.getItemDescriptionFromId(_recipeIdOnFocus);
			var ingredients:String = getIngredientText(_recipeIdOnFocus);
			var enhancements:Dictionary = GCItemData.getUpgradeEnhancementsFromId(_recipeIdOnFocus);
			
			// Add the description text
			_descriptionText = new GCTextField();
			_descriptionText.setStyle(GCTextField.TEXT_TYPE_LEFT);
			_descriptionText.textColor = GCConstants.COLOR_WHITE;
			_descriptionText.width = _descriptionBox.width;
			_descriptionText.wordWrap = true;		
			_descriptionBox.addChild(_descriptionText);
			_descriptionText.x = _verticalPadding;
			
			_descriptionText.text = "Name: " + recipeName + "\n\n";
			_descriptionText.appendText("Description: " + description + "\n\n");
			_descriptionText.appendText("Required Items: \n");
			_lineCount = _descriptionText.height;
			
			// Add the ingredient requirement text
			addIngredientDescription(_recipeIdOnFocus);
			
			// Button logic
			_buildButton.visible = true;
			if (_canBuild)
				_buildButton.enable();
			//else
				//_buildButton.disable();
			
			if (GCConstants.LOGGING_DATA)
			{
				var o:Object = new Object();
				o["itemId"] = _recipeIdOnFocus;
				GCPlayState.logger.LogAction(new ClientAction(ClientActionType.VIEW_RECIPE, o));
			}
		}
	}
}